#include "stdafx.h"
#include "ParticleSystem.h"

namespace MyGame {

ParticleSystem::ParticleSystem(Game* game) : DrawableGameComponent(game) {
    this->bulletParticle = new BulletParticle(this->GetGame());
    this->bulletParticle->SetBillboard(true);
    this->explosion = new Explosion(this->GetGame());
    this->explosion->SetBillboard(true);
    this->smoke = new Smoke(this->GetGame());
    this->smoke->SetBillboard(true);
    this->particles = new list<Particle*>();
}

ParticleSystem::~ParticleSystem(void) {
    d3d::Delete(this->bulletParticle);
    d3d::Delete(this->explosion);
    d3d::Delete(this->smoke);

    list<Particle*>::const_iterator it = this->particles->begin();
    while (it != this->particles->end()) {
        Particle* particle = *it;
        it = this->particles->erase(it);
        d3d::Delete(particle);
    }

    d3d::Delete(this->particles);
}

BulletParticle* ParticleSystem::GetBulletParticle() const {
    return this->bulletParticle;
}

Explosion* ParticleSystem::GetExplosion() const {
    return this->explosion;
}

Smoke* ParticleSystem::GetSmoke() const {
    return this->smoke;
}

void ParticleSystem::Add(Particle* particle) {
    this->particles->push_back(particle);
}

void ParticleSystem::Draw(FLOAT timeDelta) {
    this->particles->sort(Particle::Compare);
    for (list<Particle*>::const_iterator it = this->particles->begin(); it != this->particles->end(); ++it) {
        Particle* particle = *it;
        if (particle->Effect == NULL) {
            continue;
        }

        particle->Effect->SetPosition(particle->Position);

        FLOAT alpha = (particle->LifeMax - particle->Life) / particle->LifeMax;
        if (particle->BeginScale != particle->EndScale) {
            D3DXVECTOR3 scale;
            D3DXVec3Lerp(&scale, &particle->BeginScale, &particle->EndScale, alpha);
            particle->Effect->SetScale(scale);
        } else {
            particle->Effect->SetScale(particle->BeginScale);
        }

        particle->Effect->SetAlpha(alpha);
        particle->Effect->Draw(timeDelta);
    }
}

void ParticleSystem::Initialize() {
    this->bulletParticle->Initialize();
    this->explosion->Initialize();
    this->smoke->Initialize();
}

void ParticleSystem::LoadContent() {
    this->bulletParticle->LoadContent();
    this->explosion->LoadContent();
    this->smoke->LoadContent();
}

void ParticleSystem::Remove(Particle* particle) {
    list<Particle*>::const_iterator it = this->particles->begin();
    while (it != this->particles->end()) {
        if (*it == particle) {
            it = this->particles->erase(it);
            break;
        }

        ++it;
    }
}

void ParticleSystem::Update(FLOAT timeDelta) {
    list<Particle*>::const_iterator it = this->particles->begin();
    while (it != this->particles->end()) {
        Particle* particle = (*it);
        if (particle->Life < 0) {
            it = this->particles->erase(it);
            d3d::Delete(particle);
        } else {
            if (particle->LifeMax > 0) {
                particle->Life -= timeDelta;
            }

            if  (particle->Speed != D3DXVECTOR3(0,0,0)) {
                particle->Speed += particle->Gravity * timeDelta;
                particle->Position += particle->Speed * timeDelta;
            }
            ++it;
        }
    }
}

}
